home *** CD-ROM | disk | FTP | other *** search
- Path: newsfeed.concentric.net!news
- From: "Alan L. Lovejoy" <alovejoy@concentric.net>
- Newsgroups: comp.lang.java,comp.lang.c++,comp.lang.smalltalk
- Subject: Re: Will Java kill C++?
- Date: Sun, 14 Apr 1996 01:04:16 -0700
- Organization: Modulation
- Message-ID: <3170B180.51A8@concentric.net>
- References: <31682FFE.2781E494@bbn.com> <DpJyGG.FKK@hkuxb.hku.hk> <denatale-1004960822260001@grail1506.nando.net> <dbell-1104960125190001@wholder2.cts.com> <goochb.327.000893D1@rwi.com> <dbell-1104961159050001@wholder2.cts.com> <316D8523.74D7@concentric.net> <dbell-1104962256020001@wholder2.cts.com> <316E3FB6.38F7@concentric.net> <dbell-1204961508460001@wholder2.cts.com> <316F8A35.5189@concentric.net> <dbell-1304961718060001@wholder2.cts.com>
- NNTP-Posting-Host: cnc009054.concentric.net
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Transfer-Encoding: 7bit
- X-Mailer: Mozilla 2.01Gold (Win95; U)
-
- Doug Bell wrote:
- (with parts where substantial agreement has been reached left out)
- > "Alan L. Lovejoy" <alovejoy@concentric.net> wrote:
- > > Firstly, if Java is to be used to code applets on WWW pages, then it will
- > > always be interpreted (when used for that purpose)--unless the world happens
- > > to standardize on exactly one instruction set to the exclusion of all others.
- >
- > Here's my opportunity to teach you something. :)
- >
- > Currently, Java is executed through interpretation. This is already
- > starting to change as the first "just in time" compilers (or JIT
- > compilers) for java are becoming available. A JIT compiler will translate
- > the machine-independent byte-codes of Java into directly executable
- > machine code. This translation happens as the code is loaded off the
- > network, and in fact should occur faster than the code is downloaded
- > across the network, so there should be *no* additional delays imposed by
- > this translation. The resulting machine code is then executed. Web
- > browsers most certainly will use JIT compilers in the near future. Stand
- > alone Java applications can either be translated as they are loaded, or
- > translated once for a platform.
- >
- > The performance of this translated code is yet to be determined, but it
- > should be able to achieve somewhere between 50% and 100% the speed of
- > natively compiled C or C++ code.
- >
- > In addition, Sun is already working on processors which will execute the
- > Java bytecodes directly. How these will affect the market remains
- > unclear, but it serves to point out that there are even greater
- > performance possibilities already in the works.
-
- For the past ten years, the ParcPlace (now ParcPlace-Digitalk) VM has worked
- more or less as you describe the JIT compiler--although there are differences.
- This is why the recently reported benchmarks show Smalltalk as being many
- times faster than Java. I fully expect this to change over the next year.
-
- Xerox PARC developed not just Smalltalk, but Smalltalk workstations that
- used bit-sliced microcoded processors to execute Smalltalk bytecodes in
- hardware. There was a university project in the 80's that developed a
- Smalltalk CPU called SOAR.
-
- But these specialized processors suffered the same fate as the infamous
- "LISP machines." The commerical RISC processors ate their lunch, for several
- reasons:
-
- 1. The general purpose RISCs would run all software, not just Smalltalk
- or LISP.
-
- 2. They were often faster than the special purpose processors, because
- more resources were expended in their design and manufacture--because
- the return on investment was higher.
-
- 3. The world wanted to standardize on MS-DOS and UNIX.
-
- Another point to consider: Smalltalk (and LISP) would probably benefit from
- a Java processor as much as would Java itself. At the "bytecode" level,
- syntax differences and static typing are no longer relevant.
-
- > > The main differences between Java and Smalltalk (as languages, not as
- > development
- > > environments or delivery platforms):
- > >
- > > 1. Java is statically typed, Smalltalk is not (although both use dynamic
- > binding).
- >
- > Maybe this my lack of understanding (as I bow to the Gods of OOP who have
- > traveled the road farther than I), but I view Java's strongly typed
- > behavior as a benefit. I realize this is probably different from what you
- > mean by statically typed.
-
- You have been blindsided by a common misuse of technical terminology.
-
- The terms "static typing" and "strong typing" are often wrongfully used as
- though they were synonyms. This misuse is endemic, and many are misled by
- it.
-
- The correct definition of "static typing" is that a) type constraints are
- enforced during program translation ("compilation"); and b) the type of
- of an object is always determinable by lexical analysis of the program text.
-
- The correct definition of "strong typing" is that type errors are prevented
- from occuring. An example of a type error would be applying the integer
- addition machine instruction to a 32-bit floating point value, and then
- using the result as though it meant something.
-
- Smalltalk, LISP and Java are all strongly typed. Only Java is also statically
- typed. Type errors can occur in both C and C++, so they are statically
- but not strongly typed.
-
- Whether static typing is good or not is another religious issue that
- I will refrain from addressing.
-
- > > 2. Smalltalk has block closures. Java doesn't even have function pointers.
- >
- > I keep seeing this. What is a block closure?
-
- Glad you asked!
-
- First, let me introduce Smalltalk-like "block closures" into C.
-
- C already has "blocks." They're the things bracketed by "{" and "}".
- The syntax is roughly: Block ::= "{" Statement {";" Statement} "}".
- For example: while (index <= 10) {printf("%i", index); index = index + 1}.
-
- To convert these into block closures, we first have to make them values
- that can be assigned to variables and passed as parameters. So we have
- to introduce the datatype "block." Then we can write code like this:
-
- block countingBlock;
- int index;
-
- countingBlock = {printf("%i", index); index = index + 1};
- index = 1;
- while (index <= 10) countingBlock;
-
- Next, we have to be able to pass parameters into a block--just like it
- was a function. In fact, you can think of a Smalltalk block as an
- anonymous function. Such a parameterized block in C might look like
- this: {(int index): printf("%i", index)}. Then we can write code
- like this:
-
- block printBlock;
- int i;
-
- printBlock = {(int index): printf("%i", index)};
- for (i = 1; i <= 10; i++) printBlock(i);
-
- Note that "printBlock" could just as easily have been passed in as a parameter
- to the function that will execute it instead of being declared just before use.
-
- Finally, we have to give the blocks closure semantics. This defines the
- meaning of external references (reads and writes to variables declared
- outside the scope of the block itself) in a precise way. Specifically,
- the resolution of variable references external to the block has to be
- closed at the time the block definition code is executed. This requires
- that function contexts be allocated on the heap and not on the stack,
- because a variable that is referred to by a closure is "live" as long as
- the closure is. Another way to think of this is that variables declared
- outside the closure, but referenced by the closure, are in effect implied
- reference parameters.
-
- One of the most powerful uses of blockClosures is for iterating over the
- contents of a collection. Let me use my extended C again to illustrate:
-
- Suppose we have defined a binary tree data structure, whose nodes are
- structs. There is a typedef for this struct named BinaryTreeNode,
- and a set of functions that implement the usual operations on binary
- trees. Additionaly, we have defined three tree enumeration functions:
- inOrderDo(), inPreOrderDo(), and inPostOrderDo(). All three functions
- take a one-argument "block" as an argument:
-
- typedef
-
- BinaryTreeNode struct {void *left, *right, *value};
- BinaryTreeBlock block {BinaryTreeNode * node};
-
- void doInOrder(BinaryTreeNode node; BinaryTreeBlock enumerationBlock) {...};
- void doInPreOrder(BinaryTreeNode node; BinaryTreeBlock enumerationBlock) {...};
- void doInPostOrder(BinaryTreeNode node; BinaryTreeBlock enumerationBlock) {...};
-
- One can then iterate over all nodes in a binary tree, applying whatever logic
- to each node that can be coded by a block closure:
-
- doInOrder(
- tree,
- {(BinaryTreeNode * node):
- addBTReeNode(copyOfTree, bTreeNodeCopy(node))}
- );
-
- Block closures are also useful for creating new control structures. In Smalltalk,
- all the traditional control structures are implemented using block closures.
-
- Of course, Smalltalk block closures aren't just "values." They're objects.
- You can send them messages. They have a class. You can add methods to that
- class.
-
- > > 3. Smalltalk is highly reflexive and permits metaprogramming. Java isn't and
- > > doesn't (compared to Smalltalk).
- >
- > English please... (sorry)
-
- A real explanation would take longer than I have. The IRS wants some of my time
- right about now (sorry). But here are some key points:
-
- 1) In Smalltalk, all values are objects.
- 2) Classes are values--and hence they are objects. Just like any other object, a class
- is itself an instance of a class. A class whose instances are themselves classes is
- called a metaclass. A metaclass is an object, and just like any other object, it is
- an instance of a class. Specifically, a metaclass is an instance of the class
- Metaclass. Metaclass is an object, and just like any other object, it is an
- instance of a class--and that class is an instance of Metaclass, so the relationship
- is circular. Both Metaclass and its class are instances of their own instances.
- 3) Classes can be assigned to variables, passed as parameters and sent messages,
- just like any other object.
- 4) You can ask any object for its class. This is an example of reflection.
- 5) You can add methods to any class, including system classes (for example, the
- classes Object, CompiledMethod, BlockClosure, Class and Metaclass--doing this is
- an example of metaprogramming).
- 6) You can subclass, reparent or redefine any class--including the system classes.
- 7) You can make the system use different classes than those specified by the system
- vendor for most system functions (there are some exceptions, and it would be easy
- for the system vendor to prevent the substitution of certain classes if that was
- required for system security). For example, you could make the system use some
- class other than Metaclass to instantiate metaclasses, or some class other than
- CompiledMethod to instantiate methods. More metaprogramming.
- 8) You can create/modify/remove classes programmatically as the program is running.
- Yet more metaprogramming.
- 9) You can programmatically create annonymous/lightweight classes for special purposes.
- Even more powerful metaprogramming.
- 10) The execution context is a value--and hence an object. This object represents
- the state of a thread of execution: the method activation stack, the program counter,
- the temporary variables and method arguments. Each thread (called a process in
- Smalltalk) stores an object that represents the current state of thread execution
- for that thread. And there is a pseudo-variable 'thisContext' that refers to
- the execution state of the current thread. An execution context can answer questions
- such as "what is the CompiledMethod that is currently executing," or "what object is
- the receiver of the message that was sent to invoke this method," or "what is the value
- of the third method argument" or "what context sent the message that invoked this method."
- This is deep reflection.
- 11) You can ask a class what instance variables its instances have, what messages
- its instances will understand and what code will actually execute when messages are sent
- to the instances--among other things. And you can ask methods what messages are sent
- in the body of the method, what instance variables are accessed (read or written),
- and what global values are accessed. This, too, is deep reflection.
-
- I could go on, but hopefully this begins to give you an idea of the capabilities.
-
- These metaprogramming and reflective capabilities can be used to do things such as sending
- objects over the net when the receiver of the objects has never seen or heard of the classes
- of the objects (and you can't send source code because the receiver does not have a compiler),
- or sharing of distrubuted objects by processes on different computers connected over the net.
-
- --Alan
-